using System;
using System.Collections.Generic;
using System.Text;
using Chili.Opf3.Wizard.SimplePlugin.Properties;
using System.Windows.Forms;

namespace Chili.Opf3.Wizard.SimplePlugin
{
	/// <summary>
	/// This is a sample provider class. A provider implements a plug-in for the Opf3 Wizard. The class
	/// implements the IObjectProvider interface. If you want to provide an additional language (for persistent objects) 
	/// you should implement IPersistentObjectsProvider.
	/// </summary>
	public sealed class SampleProvider : Chili.Opf3.Wizard.Shared.IObjectsProvider
	{
		// A list containing all custom pages of the plug-in.
		private List<Chili.Opf3.Wizard.Shared.UI.Page> _pages = new List<Chili.Opf3.Wizard.Shared.UI.Page>();
		// This class hols the state of the plug-in.
		private StateBag _stateBag = new StateBag();
		// This list conatins all items created by the plug-in.
		private List<Chili.Opf3.Wizard.Shared.IGeneratedObject> _items;

		/// <summary>
		/// Creates a new instance of the SampleProvider.
		/// </summary>
		public SampleProvider()
		{
			// Add the sample page to the list of pages.
			_pages.Add(new SamplePage(this, _stateBag));
		}

		#region IObjectsProvider Members

		/// <summary>
		/// Generates the objects form the project structure.
		/// </summary>
		/// <param name="project">The project containing all selected tables and fields of the database.</param>
		public void GenerateObjects(Chili.Opf3.Wizard.Shared.Project project)
		{
			// Loop over all items in the list.
			foreach (SampleItem item in _items)
			{
				// Skip all items that are not generated.
				if (!item.Generate)
					continue;

				// Fire the event that the item is now generated. This updates the UI of the wizard.
				if (GeneratingObject != null)
					GeneratingObject(this, new Chili.Opf3.Wizard.Shared.GeneratingObjectEventArgs(item.ID));

				try
				{
					// Show a messagebox to inform the user that the object is going to be generated. The plug-in
					// does nothing more here, but you could create the real objects and save them to the disk.
					if (MessageBox.Show(string.Format(Resources.GeneratingObjectText, _stateBag.Name, item.Name),
						Resources.GeneratingObjectTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes)
					{
						// Throw an exception as it was not possible to create the object.
						throw new Exception(Resources.NotPossibleToCreateObjectText);
					}
				}
				catch (Exception ex)
				{
					// We got the exception here. When invoking the event the exception is set as part of the EventArgs.
					// The wizard shows the exception message in the list.
					if (GeneratedObject != null)
						GeneratedObject(this, new Chili.Opf3.Wizard.Shared.GeneratedObjectEventArgs(item.ID, ex));
					// Go to the next item in the list.
					continue;
				}

				// No exception has happened. Signalize that the object has been created.
				if (GeneratedObject != null)
					GeneratedObject(this, new Chili.Opf3.Wizard.Shared.GeneratedObjectEventArgs(item.ID));
			}
		}

		/// <summary>
		/// Event is fired before the object is generated from the data of the <see cref="Project">Project</see> class.
		/// </summary>
		public event EventHandler<Chili.Opf3.Wizard.Shared.GeneratingObjectEventArgs> GeneratingObject;

		/// <summary>
		/// Event is fired after the object is generated from the data of the <see cref="Project">Project</see> class.
		/// </summary>
		public event EventHandler<Chili.Opf3.Wizard.Shared.GeneratedObjectEventArgs> GeneratedObject;

		/// <summary>
		/// Returns the name for the plug-in.
		/// </summary>
		public string Name
		{
			get { return Resources.Name; }
		}

		/// <summary>
		/// Returns the description for the plug-in.
		/// </summary>
		public string Description
		{
			get { return Resources.Description; }
		}

		/// <summary>
		/// Returns the version of the plug-in.
		/// </summary>
		public string Version
		{
			get { return this.GetType().Assembly.GetName().Version.ToString(); }
		}

		/// <summary>
		/// Display the about dialog for the plug-in.
		/// </summary>
		public void ShowAboutDialog()
		{
			// Show a messagebox as about window.
			MessageBox.Show(Resources.AboutDialogBoxText, Resources.AboutDialogBoxTitle, MessageBoxButtons.OK, MessageBoxIcon.Information);
		}

        /// <summary>
        /// Initialize defaults in a new project.
        /// </summary>
        /// <param name="project">The project.</param>
        public void InitializeDefaults(Chili.Opf3.Wizard.Shared.Project project)
        {
        }

		/// <summary>
		/// Deserialize the plug-in state from xml.
		/// </summary>
		/// <param name="project">The project.</param>
		/// <param name="xml">Specifies the xml document that holds the current project.</param>
		/// <param name="d">The node holding the data for the provider.</param>
		public void Deserialize(Chili.Opf3.Wizard.Shared.Project project, System.Xml.XmlDocument xml, System.Xml.XmlNode d)
		{
			// Deserialize the data that is in the given node to the current instance of the statebag.
			_stateBag.Deserialize(d);
		}

		/// <summary>
		/// Serialize the plug-in state in xml.
		/// </summary>
		/// <param name="project">The project.</param>
		/// <param name="xml">Specifies the current xml document that is created for the project.</param>
		/// <param name="d">The node where the provider should serialize its data to.</param>
		public void Serialize(Chili.Opf3.Wizard.Shared.Project project, System.Xml.XmlDocument xml, System.Xml.XmlNode d)
		{
			// Serialize the data that is in the statebag.
			d.AppendChild(_stateBag.Serialize(xml));
		}

		/// <summary>
		/// Allow the provider to build its internal data from storage's returned data.
		/// </summary>
		/// <param name="project">The current project.</param>
		public void ProcessStorage(Chili.Opf3.Wizard.Shared.Project project)
		{
			_items = new List<Chili.Opf3.Wizard.Shared.IGeneratedObject>();

			// Loop over all tables in the project and add it to the internal list of items.
			foreach (Chili.Opf3.Wizard.Shared.Storages.Table table in project.Tables)
			{
				_items.Add(new SampleItem(table));
			}
		}

		/// <summary>
		/// Returns a list of pages displayed by the class.
		/// </summary>
		public List<Chili.Opf3.Wizard.Shared.UI.Page> Pages
		{
			get { return _pages; }
		}

		/// <summary>
		/// Gets the language name supported by this tool. Or null if no explicit language
		/// is supported.
		/// </summary>
		public string LanguageName
		{
			get { return Resources.LanguageName; }
		}

		/// <summary>
		/// Returns the list of objects that are generated.
		/// </summary>
		public List<Chili.Opf3.Wizard.Shared.IGeneratedObject> GetObjectsList()
		{
			// Return the items here. They are requested by the final wizard page to display them in the listview.
			return _items;
		}

		#endregion
	}
}
